#ifndef __HEXCEPTIONS_H__
#define __HEXCEPTIONS_H__

#include <stdexcept>
#include <string>
#include <iostream>
#include "HXD1.h"

enum class HECode {NOEXC = 0, FTLERR, SMTERR, STXERR, UKNERR, UNSSIT};
// No exception, Fatal error, Semantic error, Syntax error, Unknown, unsupported situation.

class SemanticException : public std::logic_error {
	// Design like this temporarily
private:
	// The location of the error token
	size_t _line_no;
	size_t _pos_in_line;
	std::string _text;
public:
	SemanticException(const std::string &msg, size_t line_no, size_t pos_in_line,
		std::string text)
		: std::logic_error(msg), _line_no(line_no), _pos_in_line(pos_in_line),
		_text(text) { }
	virtual void display(void) const {
		std::cerr << Normal_error << "line " << _line_no << ':'
			<< _pos_in_line << ": '" << _text << "' " << what() << std::endl;
	}
};

class SyntaxException : public std::logic_error {
private:
// If the position is not easy to get, just use 0 as default
	size_t _line_no;
	size_t _pos_in_line;
public:
	SyntaxException(const std::string &msg = "syntax",
		size_t line_no = 0U, size_t pos_in_line = 0U)
		: std::logic_error(msg), _line_no(line_no), _pos_in_line(pos_in_line)
		{ }
	virtual void display(void) const {
		if (_line_no > 0U)
			std::cerr << Normal_error << "syntax at line " << _line_no << ':'
				<< _pos_in_line << ' ' << what() << std::endl;
		else
			std::cerr << Normal_error << what() << std::endl;
	}
};

class UnsupportedSituation : public std::logic_error {
public:
	UnsupportedSituation(const std::string &msg)
		: std::logic_error(msg) { }
	virtual void display(void) const {
		std::cerr << Fatal_error << "unsupported situation: "
			<< what() << std::endl;
	}
};

#endif

